home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / arch / blackfin / include / asm / uaccess.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  6.8 KB  |  272 lines

  1. /* Changes made by Lineo Inc.    May 2001
  2.  *
  3.  * Based on: include/asm-m68knommu/uaccess.h
  4.  */
  5.  
  6. #ifndef __BLACKFIN_UACCESS_H
  7. #define __BLACKFIN_UACCESS_H
  8.  
  9. /*
  10.  * User space memory access functions
  11.  */
  12. #include <linux/sched.h>
  13. #include <linux/mm.h>
  14. #include <linux/string.h>
  15.  
  16. #include <asm/segment.h>
  17. #ifdef CONFIG_ACCESS_CHECK
  18. # include <asm/bfin-global.h>
  19. #endif
  20.  
  21. #define get_ds()        (KERNEL_DS)
  22. #define get_fs()        (current_thread_info()->addr_limit)
  23.  
  24. static inline void set_fs(mm_segment_t fs)
  25. {
  26.     current_thread_info()->addr_limit = fs;
  27. }
  28.  
  29. #define segment_eq(a,b) ((a) == (b))
  30.  
  31. #define VERIFY_READ    0
  32. #define VERIFY_WRITE    1
  33.  
  34. #define access_ok(type, addr, size) _access_ok((unsigned long)(addr), (size))
  35.  
  36. static inline int is_in_rom(unsigned long addr)
  37. {
  38.     /*
  39.      * What we are really trying to do is determine if addr is
  40.      * in an allocated kernel memory region. If not then assume
  41.      * we cannot free it or otherwise de-allocate it. Ideally
  42.      * we could restrict this to really being in a ROM or flash,
  43.      * but that would need to be done on a board by board basis,
  44.      * not globally.
  45.      */
  46.     if ((addr < _ramstart) || (addr >= _ramend))
  47.         return (1);
  48.  
  49.     /* Default case, not in ROM */
  50.     return (0);
  51. }
  52.  
  53. /*
  54.  * The fs value determines whether argument validity checking should be
  55.  * performed or not.  If get_fs() == USER_DS, checking is performed, with
  56.  * get_fs() == KERNEL_DS, checking is bypassed.
  57.  */
  58.  
  59. #ifndef CONFIG_ACCESS_CHECK
  60. static inline int _access_ok(unsigned long addr, unsigned long size) { return 1; }
  61. #else
  62. #ifdef CONFIG_ACCESS_OK_L1
  63. extern int _access_ok(unsigned long addr, unsigned long size)__attribute__((l1_text));
  64. #else
  65. extern int _access_ok(unsigned long addr, unsigned long size);
  66. #endif
  67. #endif
  68.  
  69. /*
  70.  * The exception table consists of pairs of addresses: the first is the
  71.  * address of an instruction that is allowed to fault, and the second is
  72.  * the address at which the program should continue.  No registers are
  73.  * modified, so it is entirely up to the continuation code to figure out
  74.  * what to do.
  75.  *
  76.  * All the routines below use bits of fixup code that are out of line
  77.  * with the main instruction path.  This means when everything is well,
  78.  * we don't even have to jump over them.  Further, they do not intrude
  79.  * on our cache or tlb entries.
  80.  */
  81.  
  82. struct exception_table_entry {
  83.     unsigned long insn, fixup;
  84. };
  85.  
  86. /* Returns 0 if exception not found and fixup otherwise.  */
  87. extern unsigned long search_exception_table(unsigned long);
  88.  
  89. /*
  90.  * These are the main single-value transfer routines.  They automatically
  91.  * use the right size if we just have the right pointer type.
  92.  */
  93.  
  94. #define put_user(x,p)                        \
  95.     ({                            \
  96.         int _err = 0;                    \
  97.         typeof(*(p)) _x = (x);                \
  98.         typeof(*(p)) *_p = (p);                \
  99.         if (!access_ok(VERIFY_WRITE, _p, sizeof(*(_p)))) {\
  100.             _err = -EFAULT;                \
  101.         }                        \
  102.         else {                        \
  103.         switch (sizeof (*(_p))) {            \
  104.         case 1:                        \
  105.             __put_user_asm(_x, _p, B);        \
  106.             break;                    \
  107.         case 2:                        \
  108.             __put_user_asm(_x, _p, W);        \
  109.             break;                    \
  110.         case 4:                        \
  111.             __put_user_asm(_x, _p,  );        \
  112.             break;                    \
  113.         case 8: {                    \
  114.             long _xl, _xh;                \
  115.             _xl = ((long *)&_x)[0];            \
  116.             _xh = ((long *)&_x)[1];            \
  117.             __put_user_asm(_xl, ((long *)_p)+0, );    \
  118.             __put_user_asm(_xh, ((long *)_p)+1, );    \
  119.         } break;                    \
  120.         default:                    \
  121.             _err = __put_user_bad();        \
  122.             break;                    \
  123.         }                        \
  124.         }                        \
  125.         _err;                        \
  126.     })
  127.  
  128. #define __put_user(x,p) put_user(x,p)
  129. static inline int bad_user_access_length(void)
  130. {
  131.     panic("bad_user_access_length");
  132.     return -1;
  133. }
  134.  
  135. #define __put_user_bad() (printk(KERN_INFO "put_user_bad %s:%d %s\n",\
  136.                            __FILE__, __LINE__, __func__),\
  137.                            bad_user_access_length(), (-EFAULT))
  138.  
  139. /*
  140.  * Tell gcc we read from memory instead of writing: this is because
  141.  * we do not write to any memory gcc knows about, so there are no
  142.  * aliasing issues.
  143.  */
  144.  
  145. #define __ptr(x) ((unsigned long *)(x))
  146.  
  147. #define __put_user_asm(x,p,bhw)                \
  148.     __asm__ (#bhw"[%1] = %0;\n\t"            \
  149.          : /* no outputs */            \
  150.          :"d" (x),"a" (__ptr(p)) : "memory")
  151.  
  152. #define get_user(x,p)                            \
  153.     ({                                \
  154.         int _err = 0;                        \
  155.         typeof(*(p)) *_p = (p);                    \
  156.         if (!access_ok(VERIFY_READ, _p, sizeof(*(_p)))) {    \
  157.             _err = -EFAULT;                    \
  158.         }                            \
  159.         else {                            \
  160.         switch (sizeof(*(_p))) {                \
  161.         case 1:                            \
  162.             __get_user_asm(x, _p, B,(Z));            \
  163.             break;                        \
  164.         case 2:                            \
  165.             __get_user_asm(x, _p, W,(Z));            \
  166.             break;                        \
  167.         case 4:                            \
  168.             __get_user_asm(x, _p,  , );            \
  169.             break;                        \
  170.         case 8: {                        \
  171.             unsigned long _xl, _xh;                \
  172.             __get_user_asm(_xl, ((unsigned long *)_p)+0,  , ); \
  173.             __get_user_asm(_xh, ((unsigned long *)_p)+1,  , ); \
  174.             ((unsigned long *)&x)[0] = _xl;            \
  175.             ((unsigned long *)&x)[1] = _xh;            \
  176.         } break;                        \
  177.         default:                        \
  178.             x = 0;                        \
  179.             printk(KERN_INFO "get_user_bad: %s:%d %s\n",    \
  180.                    __FILE__, __LINE__, __func__);    \
  181.             _err = __get_user_bad();            \
  182.             break;                        \
  183.         }                            \
  184.         }                            \
  185.         _err;                            \
  186.     })
  187.  
  188. #define __get_user(x,p) get_user(x,p)
  189.  
  190. #define __get_user_bad() (bad_user_access_length(), (-EFAULT))
  191.  
  192. #define __get_user_asm(x,p,bhw,option)                \
  193.     {                            \
  194.         unsigned long _tmp;                \
  195.         __asm__ ("%0 =" #bhw "[%1]"#option";\n\t"    \
  196.              : "=d" (_tmp)                \
  197.              : "a" (__ptr(p)));            \
  198.         (x) = (__typeof__(*(p))) _tmp;            \
  199.     }
  200.  
  201. #define __copy_from_user(to, from, n) copy_from_user(to, from, n)
  202. #define __copy_to_user(to, from, n) copy_to_user(to, from, n)
  203. #define __copy_to_user_inatomic __copy_to_user
  204. #define __copy_from_user_inatomic __copy_from_user
  205.  
  206. #define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n))\
  207.                                  return retval; })
  208.  
  209. #define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n))\
  210.                                                    return retval; })
  211.  
  212. static inline long copy_from_user(void *to,
  213.                   const void __user * from, unsigned long n)
  214. {
  215.     if (access_ok(VERIFY_READ, from, n))
  216.         memcpy(to, from, n);
  217.     else
  218.         return n;
  219.     return 0;
  220. }
  221.  
  222. static inline long copy_to_user(void *to,
  223.                 const void __user * from, unsigned long n)
  224. {
  225.     if (access_ok(VERIFY_WRITE, to, n))
  226.         memcpy(to, from, n);
  227.     else
  228.         return n;
  229.     return 0;
  230. }
  231.  
  232. /*
  233.  * Copy a null terminated string from userspace.
  234.  */
  235.  
  236. static inline long strncpy_from_user(char *dst,
  237.                                      const char *src, long count)
  238. {
  239.     char *tmp;
  240.     if (!access_ok(VERIFY_READ, src, 1))
  241.         return -EFAULT;
  242.     strncpy(dst, src, count);
  243.     for (tmp = dst; *tmp && count > 0; tmp++, count--) ;
  244.     return (tmp - dst);
  245. }
  246.  
  247. /*
  248.  * Return the size of a string (including the ending 0)
  249.  *
  250.  * Return 0 on exception, a value greater than N if too long
  251.  */
  252. static inline long strnlen_user(const char *src, long n)
  253. {
  254.     return (strlen(src) + 1);
  255. }
  256.  
  257. #define strlen_user(str) strnlen_user(str, 32767)
  258.  
  259. /*
  260.  * Zero Userspace
  261.  */
  262.  
  263. static inline unsigned long __clear_user(void *to, unsigned long n)
  264. {
  265.     memset(to, 0, n);
  266.     return 0;
  267. }
  268.  
  269. #define clear_user(to, n) __clear_user(to, n)
  270.  
  271. #endif                /* _BLACKFIN_UACCESS_H */
  272.